#include "QVTKInteractorStyle.h"

#include "QIVtkSelectionPipeline.h"

#include "TopoDS_Edge.hxx"
#include "TopoDS.hxx"
#include "BRep_Tool.hxx"
#include <TopoDS_Vertex.hxx>
#include <vtkNamedColors.h>
#include <RWTools.h>
#include <BRepBndLib.hxx>
#include <TopExp.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepExtrema_ExtCC.hxx>
#include <vtkCamera.h>
#include <vtkCoordinate.h>
#include <vtkPointPlacer.h>


// macro: a vtkNew method to all member functions
vtkStandardNewMacro(QVTKInteractorStyle)

QVTKInteractorStyle::QVTKInteractorStyle()
{
	vtkNew<vtkNamedColors> colors;
	LastPickedActor = nullptr;
	baseProperty->SetColor(colors->GetColor4d("RoyalBlue").GetData());
	baseProperty->SetOpacity(0.5);

	highlightProperty->SetColor(1, 0, 0);
	highlightProperty->SetDiffuse(1.0);
	highlightProperty->SetSpecular(0.0);
	highlightProperty->SetOpacity(0.5);
}

///
/// \param pipelinesMap 清除 ID-Pipeline Map 中的数据
/// \param doHighlighting 清除触碰高亮
/// \param doSelection 清除选择高亮
static void ClearHighlightAndSelection(NCollection_DataMap<IVtk_IdType, Handle(QIVtkSelectionPipeline) > pipelinesMap, 
	const Standard_Boolean doHighlighting, const Standard_Boolean doSelection) 
{
	if (!doHighlighting && !doSelection) 
	{
		return;
	}

	NCollection_DataMap<IVtk_IdType, Handle(QIVtkSelectionPipeline) >::Iterator pIt(pipelinesMap);
	for (; pIt.More(); pIt.Next()) 
	{
		const Handle(QIVtkSelectionPipeline)& pipeline = pIt.Value();

		if (doHighlighting) 
		{
			pipeline->ClearHighlightFilters();
		}

		if (doSelection) 
		{
			pipeline->ClearSelectionFilters();
		}
	}
}

QVTKInteractorStyle::~QVTKInteractorStyle() 
{

}

//----------------------------------------------------------------------------
void QVTKInteractorStyle::addPipeline( const Handle(QIVtkSelectionPipeline) pipeline, IVtk_IdType shapeID) 
{
	_shapePipelinesMap.Bind(shapeID, pipeline);
	_selectedSubShapeIdsMap.Bind(shapeID, new IVtk_ShapeIdList());
}

void QVTKInteractorStyle::removePipeline(IVtk_IdType id)
{
	Handle(QIVtkSelectionPipeline) deletePipeline = _shapePipelinesMap.Find(id);
	if (ContainsActor(_selectPipelines, deletePipeline))
	{
		//RemoveActor(_selectPipelines, deletePipeline);
		_selectPipelines.erase(std::remove(_selectPipelines.begin(), _selectPipelines.end(), deletePipeline), _selectPipelines.end());
	}
	_shapePipelinesMap.UnBind(id);
}


void QVTKInteractorStyle::setSelectionMode(IVtk_SelectionMode mode) 
{
	if (_shapePipelinesMap.IsEmpty())
	{
		return;
	}

	// 清空已选择的shape
	NCollection_DataMap<IVtk_IdType, IVtk_ShapeIdList*>::Iterator sIt(_selectedSubShapeIdsMap);
	for (; sIt.More(); sIt.Next()) 
	{
		IVtk_ShapeIdList* selectedSubShapeIds = sIt.Value();
		selectedSubShapeIds->Clear();
	}

	ClearHighlightAndSelection(_shapePipelinesMap, Standard_True, Standard_True);

	//清空所有的选择模式
	NCollection_DataMap<IVtk_IdType, Handle(QIVtkSelectionPipeline) >::Iterator pIt(_shapePipelinesMap);
	for (; pIt.More(); pIt.Next()) 
	{
		const Handle(QIVtkSelectionPipeline)& pipeline = pIt.Value();

		// Deactivate all current selection modes
		IVtk_SelectionModeList modeList = _occtpicker->GetSelectionModes(pipeline->Actor());

		for (IVtk_SelectionMode selMode : modeList) 
		{
			_occtpicker->SetSelectionMode(selMode, false);
		}
	}
	// Set given selection mode
	if (mode == SM_None) 
	{
		_occtpicker->SetSelectionMode(mode, false);
		_occtPickerEnabled = false;
	}
	else 
	{
		_occtpicker->SetSelectionMode(mode, true);
		_occtPickerEnabled = true;
		if (mode == SM_Vertex) {
			_occtpicker->SetTolerance(10);
		}
		else {
			_occtpicker->SetTolerance(0.5);
		}

	}
	_currentSelectionMode = mode;
}

//void QVTKInteractorStyle::OnSelection(const Standard_Boolean appendId) 
//{
//	vtkSmartPointer<vtkActorCollection> anActorCollection
//		= _occtpicker->GetPickedActors();
//
//	if (anActorCollection) {
//		auto res = anActorCollection->GetNumberOfItems();
//		if (res != 0) {
//			// Clear previous selection.
//			ClearHighlightAndSelection(_shapePipelinesMap, Standard_False, Standard_True);
//		}
//
//		anActorCollection->InitTraversal();
//		while (vtkActor* anActor = anActorCollection->GetNextActor()) {
//			IVtkTools_ShapeDataSource* aDataSource
//				= IVtkTools_ShapeObject::GetShapeSource(anActor);
//			if (!aDataSource) {
//				continue;
//			}
//
//			IVtkOCC_Shape::Handle anOccShape = aDataSource->GetShape();
//
//			if (anOccShape.IsNull()) {
//				continue;
//			}
//
//			IVtk_IdType aShapeID = anOccShape->GetId();
//
//			Handle(Message_Messenger) anOutput = Message::DefaultMessenger();
//
//			if (!_shapePipelinesMap.IsBound(aShapeID)) {
//				anOutput->SendWarning()
//					<< "Warning: there is no VTK pipeline registered for picked shape"
//					<< std::endl;
//				continue;
//			}
//
//			const Handle(QIVtkSelectionPipeline)& pipeline = _shapePipelinesMap.Find(aShapeID);
//			IVtk_ShapeIdList* selectedSubShapeIds = _selectedSubShapeIdsMap.Find(aShapeID);
//			/*if (m_currSelector) {
//				m_currSelector->SetTag(pipeline->GetShapeID());
//			}*/
//
//
//			IVtkTools_SubPolyDataFilter* aFilter = pipeline->GetSelectionFilter();
//
//			// Set the selected sub-shapes ids to subpolydata filter.
//			IVtk_ShapeIdList aSubShapeIds;
//			if (_currentSelectionMode == IVtk_SelectionMode::SM_Shape) {
//				aSubShapeIds = _occtpicker->GetPickedShapesIds(Standard_False);
//			}
//			else {
//				aSubShapeIds = _occtpicker->GetPickedSubShapesIds(aShapeID);
//			}
//
//			if (!appendId) {
//				if (m_currSelector) {
//					m_currSelector->clearSelectedShape();
//				}
//				_selectedShapes.clear();
//				selectedSubShapeIds->Clear();
//			}
//
//			for (auto shapeID : aSubShapeIds) {
//				if (!selectedSubShapeIds->Contains(shapeID)) {
//					// If selected Ids list does not contain shape then append it.
//					selectedSubShapeIds->Append(aSubShapeIds);
//					if (m_currSelector) {
//						auto aSubShape = anOccShape->GetSubShape(shapeID);
//
//						auto result = m_currSelector->addSelectedShape(aSubShape);
//						if (!result) return;
//					}
//				}
//				else {
//					// Selecting the shape again causes deselecting it.
//					selectedSubShapeIds->Remove(shapeID);
//					if (m_currSelector) {
//						const TopoDS_Shape& aSubShape = anOccShape->GetSubShape(shapeID);
//						auto result = m_currSelector->deleteSelectedShape(aSubShape);
//						if (!result) return;
//					}
//				}
//			}
//
//			// If selected Ids list is empty then any selection will not be made
//			if (selectedSubShapeIds->IsEmpty()) {
//				if (_currentSelectionMode == SM_Solid) {
//					if (m_currSelector) {
//						auto aShape = anOccShape->GetShape();
//						auto result = m_currSelector->addSelectedShape(aShape);
//						if (!result) return;
//					}
//				}
//				else {
//					return;
//				}
//			}
//
//			// Get ids of cells for picked subshapes
//			IVtk_ShapeIdList aSubIds;
//			IVtk_ShapeIdList::Iterator aMetaIds(*selectedSubShapeIds);
//			_selectedShapes.clear();
//			for (; aMetaIds.More(); aMetaIds.Next()) {
//				IVtk_ShapeIdList aSubSubIds = anOccShape->GetSubIds(aMetaIds.Value());
//				const TopoDS_Shape& aSubShape = anOccShape->GetSubShape(aMetaIds.Value());
//				_selectedShapes.push_back(aSubShape);
//				m_currSelector->addSelectedShape(aSubShape);
//				aSubIds.Append(aSubSubIds);
//			}
//
//			aFilter->SetDoFiltering(!aSubIds.IsEmpty());
//			aFilter->SetData(aSubIds);
//			if (!aFilter->GetInput()) {
//				aFilter->SetInputConnection(aDataSource->GetOutputPort());
//			}
//			aFilter->Modified();
//
//			if (!pipeline.IsNull())
//				pipeline->Mapper()->Update();
//		}
//		//pipeline->Mapper()->Update();
//	}
//}

void QVTKInteractorStyle::Select(const Standard_Boolean appendId) {
	vtkSmartPointer<vtkActorCollection> anActorCollection
		= _occtpicker->GetPickedActors();
	gp_Pnt pickPos(_occtpicker->GetPickPosition()[0], _occtpicker->GetPickPosition()[1], _occtpicker->GetPickPosition()[2]);

	if (anActorCollection) {
		auto res = anActorCollection->GetNumberOfItems();
		if (res != 0) {
			// Clear previous selection.
			ClearHighlightAndSelection(_shapePipelinesMap, Standard_False, Standard_True);
		}

		anActorCollection->InitTraversal();
		while (vtkActor* anActor = anActorCollection->GetNextActor()) {
			IVtkTools_ShapeDataSource* aDataSource
				= IVtkTools_ShapeObject::GetShapeSource(anActor);
			if (!aDataSource) {
				continue;
			}

			IVtkOCC_Shape::Handle anOccShape = aDataSource->GetShape();

			if (anOccShape.IsNull()) {
				continue;
			}

			IVtk_IdType aShapeID = anOccShape->GetId();
			auto type = anOccShape->GetShape().ShapeType();
			Handle(Message_Messenger) anOutput = Message::DefaultMessenger();

			if (!_shapePipelinesMap.IsBound(aShapeID)) {
				anOutput->SendWarning()
					<< "Warning: there is no VTK pipeline registered for picked shape"
					<< std::endl;
				continue;
			}

			const Handle(QIVtkSelectionPipeline)& pipeline = _shapePipelinesMap.Find(aShapeID);
			IVtk_ShapeIdList* selectedSubShapeIds = _selectedSubShapeIdsMap.Find(aShapeID);

			IVtkTools_SubPolyDataFilter* aFilter = pipeline->GetSelectionFilter();

			// Set the selected sub-shapes ids to subpolydata filter.
			IVtk_ShapeIdList aSubShapeIds;
			if (_currentSelectionMode == IVtk_SelectionMode::SM_Solid) {
				aSubShapeIds = _occtpicker->GetPickedShapesIds(Standard_False);
			}
			else {
				aSubShapeIds = _occtpicker->GetPickedSubShapesIds(aShapeID);
			}

			if (!appendId) {
				if (m_currSelector) {
					m_currSelector->clearSelectedShape();
				}
				_selectedShapes.clear();
				selectedSubShapeIds->Clear();
			}


			for (auto shapeID : aSubShapeIds) {
				if (!selectedSubShapeIds->Contains(shapeID)) {
					// If selected Ids list does not contain shape then append it.
					selectedSubShapeIds->Append(shapeID);
					if (m_currSelector) {
						auto aSubShape = anOccShape->GetSubShape(shapeID);
						auto result = m_currSelector->addSelectedShape(aSubShape);
						if (!result) return;
					}
				}
				else {
					// Selecting the shape again causes deselecting it.
					selectedSubShapeIds->Remove(shapeID);
					//pipeline->Actor()->GetProperty() = LastPickedProperty;
					if (m_currSelector) {
						const TopoDS_Shape& aSubShape = anOccShape->GetSubShape(shapeID);
						auto result = m_currSelector->deleteSelectedShape(aSubShape);
						if (!result) return;
					}
					if (_currentSelectionMode == SM_Solid) {
						this->LastPickedActor->GetProperty()->DeepCopy(this->baseProperty);
						return;
					}

				}
			}


			// 单独创建的Edge 和 Face不会被选中，需要单独直接加入Selector
			if (selectedSubShapeIds->IsEmpty()) {
				if (m_currSelector) {
					//已选择Actor重复选择取消高亮
					if (!_selectPipelines.empty()) {
						auto it = std::find(_selectPipelines.begin(), _selectPipelines.end(), pipeline);
						if (it != _selectPipelines.end()) {
                            _selectPipelines.erase(it);
							//_selectedShapes.erase(anOccShape->GetShape());
							m_currSelector->deleteSelectedShape(anOccShape->GetShape());
							vtkNew<vtkNamedColors> colors;
							this->LastPickedActor->GetProperty()->SetColor(colors->GetColor4d("RoyalBlue").GetData());

						}
					}
					this->LastPickedActor = pipeline->Actor();
					auto aShape = anOccShape->GetShape();
					auto result = m_currSelector->addSelectedShape(aShape);
					selectedSubShapeIds->Append(anOccShape->GetId());
					_selectedShapes.push_back(aShape);
					_selectPipelines.push_back(pipeline);
					pipeline->Actor()->GetProperty()->SetColor(1, 0, 0);
					pipeline->Actor()->GetProperty()->SetDiffuse(1.0);
					pipeline->Actor()->GetProperty()->SetSpecular(0.0);
					pipeline->Actor()->GetProperty()->SetOpacity(0.5);
					if (stretchOperation) {
						m_currSelector->SelectedStretchSubShape(pipeline->getShape(),pipeline);
					}
					
					if (!result) return;
				}
			}

			if (_currentSelectionMode == SM_Solid) {

				this->LastPickedActor = pipeline->Actor();
				//Hilight the whole shape
				if (this->LastPickedActor)
				{
					// Highlight the picked actor by changing its properties
					this->LastPickedActor->GetProperty()->SetColor(1, 0, 0);
					this->LastPickedActor->GetProperty()->SetDiffuse(1.0);
					this->LastPickedActor->GetProperty()->SetSpecular(0.0);
					this->LastPickedActor->GetProperty()->SetOpacity(0.5);
					IVtkTools_ShapeDataSource* aDataSource
						= IVtkTools_ShapeObject::GetShapeSource(LastPickedActor);

					IVtkOCC_Shape::Handle anOccShape = aDataSource->GetShape();
					auto aSubShape = anOccShape->GetSubShape(pipeline->GetShapeID());
					_selectedShapes.push_back(aSubShape);
					_selectPipelines.push_back(pipeline);
					m_currSelector->addSelectedShape(aSubShape);
					if (brepOperation) {
						m_currSelector->SelctedShapePipeline(pipeline);
					}
					else if (stretchOperation) {
						m_currSelector->SelectedStretchSubShape(pipeline->getShape(),pipeline);
					}
					else if (hollowOperation) {
                        m_currSelector->SelectedHollowShape(pipeline->getShape(), pipeline);
					}

				}

			}
			else {
				// Get ids of cells for picked subshapes
				IVtk_ShapeIdList aSubIds;
				IVtk_ShapeIdList::Iterator aMetaIds(*selectedSubShapeIds);
				_selectedShapes.clear();
				for (; aMetaIds.More(); aMetaIds.Next()) {
					IVtk_ShapeIdList aSubSubIds = anOccShape->GetSubIds(aMetaIds.Value());
					const TopoDS_Shape& aSubShape = anOccShape->GetSubShape(aMetaIds.Value());
					_selectedShapes.push_back(aSubShape);
					m_currSelector->addSelectedShape(aSubShape);
					aSubIds.Append(aSubSubIds);

					if (_currentSelectionMode == SM_Edge && transform) {
						m_currSelector->SelectedEdgeShape(aSubShape,pipeline);
						_selectPipelines.push_back(pipeline);
						return; //旋转轴选择成功，结束
					}
					else if (stretchOperation) {

						m_currSelector->SelectedStretchSubShape(aSubShape, pipeline);
					}
					else if (revolOperation) {
						m_currSelector->SelectedRevolSubShape(aSubShape,pipeline);
					}
					else if (filletOperation){
						m_currSelector->SelectedFilletShape(aSubShape, pipeline);
					}
					else if (hollowOperation) {
						m_currSelector->SelectedHollowShape(aSubShape, pipeline);
					}
				}
				
				aFilter->SetDoFiltering(!aSubIds.IsEmpty());
				aFilter->SetData(aSubIds);
				if (!aFilter->GetInput()) {
					aFilter->SetInputConnection(aDataSource->GetOutputPort());
				}
				aFilter->Modified();
			}

			//LastPickedProperty = pipeline->Actor()->GetProperty();

			if (!pipeline.IsNull())
				pipeline->Mapper()->Update();
		}
		//pipeline->Mapper()->Update();
	}
	
}

void QVTKInteractorStyle::MoveTo(Standard_Integer theX, Standard_Integer theY) 
{
	if (!_occtPickerEnabled)
	{
		return;
	}

	_occtpicker->Pick(theX, theY, 0, getRenderer());

	// Traversing results
	vtkSmartPointer<vtkActorCollection> anActorCollection = _occtpicker->GetPickedActors();

	if (anActorCollection) 
	{
		// Highlight picked subshapes
		if (_shapePipelinesMap.IsEmpty())
		{
			return;
		}

		ClearHighlightAndSelection(_shapePipelinesMap, Standard_True, Standard_False);

		anActorCollection->InitTraversal();

		while (vtkActor* anActor = anActorCollection->GetNextActor()) 
		{
			IVtkTools_ShapeDataSource* aDataSource = IVtkTools_ShapeObject::GetShapeSource(anActor);
			if (!aDataSource) 
			{
				continue;
			}

			IVtkOCC_Shape::Handle anOccShape = aDataSource->GetShape();
			if (anOccShape.IsNull()) 
			{
				continue;
			}

			IVtk_IdType aShapeID = anOccShape->GetId();

			Handle(Message_Messenger) anOutput = Message::DefaultMessenger();
			if (!_shapePipelinesMap.IsBound(aShapeID)) 
			{
				anOutput->SendWarning()
					<< "Warning: there is no VTK pipeline registered for picked shape"
					<< std::endl;
				continue;
			}

			const Handle(QIVtkSelectionPipeline)& pipeline = _shapePipelinesMap.Find(aShapeID);
			IVtk_ShapeIdList* selectedSubShapeIds = _selectedSubShapeIdsMap.Find(aShapeID);

			IVtkTools_SubPolyDataFilter* aFilter = pipeline->GetHighlightFilter();

			// 根据Shape ID获得当前Pick的所有SubShapeID
			IVtk_ShapeIdList aSubShapeIds = _occtpicker->GetPickedSubShapesIds(aShapeID);

			// If picked shape is in selected shapes then do not highlight it
			for (auto shapeID : aSubShapeIds) 
			{
				if (selectedSubShapeIds->Contains(shapeID)) 
				{
					return;
				}
			}

			// Get ids of cells for picked subshapes.
			IVtk_ShapeIdList aSubIds;
			IVtk_ShapeIdList::Iterator aMetaIds(aSubShapeIds);
			for (; aMetaIds.More(); aMetaIds.Next()) 
			{
				// 获得Pick ID对应的点、面、线的ID集合
				IVtk_ShapeIdList aSubSubIds = anOccShape->GetSubIds(aMetaIds.Value());
				aSubIds.Append(aSubSubIds);
				const TopoDS_Shape& aSubShape = anOccShape->GetSubShape(aMetaIds.Value());
				cout << "--------------------------------------------------------------" << endl;
				cout << "Sub-shape ID: " << aMetaIds.Value() << endl;
				cout << "Sub-shape type: " << aSubShape.TShape()->DynamicType()->Name() << endl;
			}
			aFilter->SetDoFiltering(!aSubIds.IsEmpty());
			aFilter->SetData(aSubIds);
			if (!aFilter->GetInput())
			{
				aFilter->SetInputConnection(aDataSource->GetOutputPort());
			}
			aFilter->Modified();

			pipeline->Mapper()->Update();

			// 重新渲染场景
			this->GetInteractor()->GetRenderWindow()->Render();
		}
	}
}


bool QVTKInteractorStyle::SelectVertex(Standard_Integer theX, Standard_Integer theY)
{
	if (curveOperation) {
		_occtpicker->SetSelectionMode(SM_Face, true);
	}
	else {
		_occtpicker->SetSelectionMode(SM_Edge, true);
	}
	_occtPickerEnabled = true;
	_occtpicker->Pick(theX, theY, 0, getRenderer());
	pickVertex = TopoDS_Vertex();
	// Traversing results
	vtkSmartPointer<vtkActorCollection> anActorCollection = _occtpicker->GetPickedActors();
	if (anActorCollection)
	{
		// Highlight picked subshapes
		if (_shapePipelinesMap.IsEmpty())
		{
			if (tempSphereActor) {
				tempSphereActor->SetVisibility(false);
			}
			_occtpicker->SetSelectionMode(SM_Vertex, true);
			return false;
		}
		anActorCollection->InitTraversal();
		auto res = anActorCollection->GetNumberOfItems();
		if (res == 0) {
			_occtpicker->SetSelectionMode(SM_Vertex, true);
			if (tempSphereActor) {
				tempSphereActor->SetVisibility(false);
			}
			if (curveOperation) {
				std::cout << "out of the sketch" << std::endl;
			}
			return false;
		}
		while (vtkActor* anActor = anActorCollection->GetNextActor())
		{
			//曲线绘制获取点
			if (curveOperation) {
				gp_Pnt pickPos(_occtpicker->GetPickPosition()[0], _occtpicker->GetPickPosition()[1], _occtpicker->GetPickPosition()[2]);
				m_currSelector->OnLeftButtonDown(pickPos);
				_occtpicker->SetSelectionMode(SM_Vertex, true);
				return true;
			}
			IVtkTools_ShapeDataSource* aDataSource = IVtkTools_ShapeObject::GetShapeSource(anActor);
			if (!aDataSource)
			{
				continue;
			}

			IVtkOCC_Shape::Handle anOccShape = aDataSource->GetShape();
			if (anOccShape.IsNull())
			{
				continue;
			}

			IVtk_IdType aShapeID = anOccShape->GetId();

			Handle(Message_Messenger) anOutput = Message::DefaultMessenger();
			if (!_shapePipelinesMap.IsBound(aShapeID))
			{
				anOutput->SendWarning()
					<< "Warning: there is no VTK pipeline registered for picked shape"
					<< std::endl;
				continue;
			}

			const Handle(QIVtkSelectionPipeline)& pipeline = _shapePipelinesMap.Find(aShapeID);
			IVtk_ShapeIdList* selectedSubShapeIds = _selectedSubShapeIdsMap.Find(aShapeID);

			IVtkTools_SubPolyDataFilter* aFilter = pipeline->GetSelectionFilter();

			// 根据Shape ID获得当前Pick的所有SubShapeID
			IVtk_ShapeIdList aSubShapeIds = _occtpicker->GetPickedSubShapesIds(aShapeID);

			// If picked shape is in selected shapes then do not highlight it
			for (auto shapeID : aSubShapeIds)
			{
				if (selectedSubShapeIds->Contains(shapeID))
				{
					return false;
				}
			}

			// Get ids of cells for picked subshapes.
			IVtk_ShapeIdList aSubIds;
			IVtk_ShapeIdList::Iterator aMetaIds(aSubShapeIds);
			for (; aMetaIds.More(); aMetaIds.Next())
			{
				// 获得Pick ID对应的点、面、线的ID集合
				IVtk_ShapeIdList aSubSubIds = anOccShape->GetSubIds(aMetaIds.Value());
				aSubIds.Append(aSubSubIds);
			}
			aFilter->SetDoFiltering(!aSubIds.IsEmpty());
			aFilter->SetData(aSubIds);
			if (!aFilter->GetInput())
			{
				aFilter->SetInputConnection(aDataSource->GetOutputPort());
			}
			aFilter->Modified();
			const TopoDS_Shape& aSubShape = anOccShape->GetSubShape(aSubIds.First());
			//选取最近点

			gp_Pnt pickPos(_occtpicker->GetPickPosition()[0], _occtpicker->GetPickPosition()[1], _occtpicker->GetPickPosition()[2]);
			pickVertex = pickNearestEdgePoint(pickPos, aSubShape);
			if (pickVertex.IsNull()) {
				_occtpicker->SetSelectionMode(SM_Vertex, true);
				if (tempSphereActor) {
					tempSphereActor->SetVisibility(false);
				}
				return false;
			}
			_occtpicker->SetSelectionMode(SM_Vertex, true);
			_occtpicker->RemoveSelectableActor(anActor);
			//可视化选择点
			if (tempSphereActor)
			{
				gp_Pnt point = BRep_Tool::Pnt(TopoDS::Vertex(pickVertex));
				tempSphereActor->SetPosition(point.X(), point.Y(), point.Z());
				tempSphereActor->SetVisibility(true);
			}
			pipeline->Mapper()->Update();
			// 重新渲染场景
			this->GetInteractor()->GetRenderWindow()->Render();
			//发送信号 点选择器获取选择点
			m_currSelector->sentVertex(pickVertex);

			return true;

		}
		
	}
	if (tempSphereActor) {
		tempSphereActor->SetVisibility(false);
	}
	_occtpicker->SetSelectionMode(SM_Vertex, true);
	return false;
}



//----------------------------------------------------------------------------
void QVTKInteractorStyle::setVTKRenderWindow(
	vtkRenderWindow* vtkRenderWindow) {
	_qvtkRenderWindow = vtkRenderWindow;
}

void QVTKInteractorStyle::setRenderer(
	const vtkSmartPointer<vtkRenderer>& theRenderer) {
	_renderer = theRenderer;
}

void QVTKInteractorStyle::setOcctPicker(
	const vtkSmartPointer<IVtkTools_ShapePicker>& thePicker) {
	_occtpicker = thePicker;
}

void QVTKInteractorStyle::setCurrSelector(OccGeoSelector* selector)
{
	m_currSelector = selector;
}

void QVTKInteractorStyle::clearCurrSelector()
{
	vtkNew<vtkNamedColors> color;
	for (Handle(QIVtkSelectionPipeline) prePipe : _selectPipelines)
	{
		prePipe->Actor()->GetProperty()->SetColor(color->GetColor4d("RoyalBlue").GetData());
	}

	_selectPipelines.clear();
	setSelectionMode(SM_None);
	m_currSelector = nullptr;
}


void QVTKInteractorStyle::OnRightButtonDown()
{
	vtkInteractorStyleTrackballCamera::OnRightButtonDown();
}

void QVTKInteractorStyle::OnLeftButtonDown() {
	lastPos[0] = this->GetInteractor()->GetEventPosition()[0];
	lastPos[1] = this->GetInteractor()->GetEventPosition()[1];

	// Invoke base class event
	//vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
}


void QVTKInteractorStyle::OnLeftButtonUp() {
	int* clickPos = this->GetInteractor()->GetEventPosition();

	//if mouse moved, is a DragEvent.
	if (clickPos[0] == lastPos[0] && clickPos[1] == lastPos[1]) {
		
		if (this->Interactor->GetShiftKey()) {
			// Append new selection to the current one
			this->Select(Standard_True);
		}
		else{
			if (_currentSelectionMode == SM_Vertex) {
				SelectVertex(clickPos[0], clickPos[1]);
			}
			else {
				// Clear previous selection
				this->Select(Standard_False);
			}
			
		}

	}
	_qvtkRenderWindow->Render();
}

void QVTKInteractorStyle::OnMouseMove() 
{
	Standard_Integer aPos[2] = 
	{
			this->Interactor->GetEventPosition()[0],
			this->Interactor->GetEventPosition()[1]
	};
	
	//暂不实现点高亮
	if (_currentSelectionMode != SM_Vertex) {
		this->MoveTo(aPos[0], aPos[1]);
	}
	vtkInteractorStyleTrackballCamera::OnMouseMove();
}

void QVTKInteractorStyle::OnKeyPress() {
	vtkInteractorStyleTrackballCamera::OnKeyPress();
}

void QVTKInteractorStyle::OnKeyRelease() {
	vtkInteractorStyleTrackballCamera::OnKeyRelease();
}

void QVTKInteractorStyle::OnMiddleButtonDown() {
	vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
}

void QVTKInteractorStyle::OnMiddleButtonUp() {
	vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
}

void QVTKInteractorStyle::RemoveSelectedActor(Handle(QIVtkSelectionPipeline) delSelPipe)
{
	vtkNew<vtkNamedColors> colors;
	if (ContainsActor(_selectPipelines, delSelPipe))
	{
		RemoveActor(_selectPipelines, delSelPipe);
		TopoDS_Shape delShape = delSelPipe->getShape();
		// 使用 std::remove_if 删除匹配的元素
		auto newEnd = std::remove_if(_selectedShapes.begin(), _selectedShapes.end(), [&delShape](const std::reference_wrapper<const TopoDS_Shape>& ref) {
			return &ref.get() == &delShape;
			});

		// 如果有元素被移除，更新容器大小
		if (newEnd != _selectedShapes.end()) {
			_selectedShapes.erase(newEnd, _selectedShapes.end());
		}
		//_selectedShapes.erase(std::remove(_selectedShapes.begin(), _selectedShapes.end(), delSelPipe->getShape()), _selectedShapes.end());
		delSelPipe->Actor()->GetProperty()->SetColor(colors->GetColor4d("RoyalBlue").GetData());
		if (_selectPipelines.empty())
		{
			setSelectionMode(SM_None);
		}
	}
}

void QVTKInteractorStyle::clearShapeMaps() {
	_shapePipelinesMap.Clear();
	_selectedSubShapeIdsMap.Clear();
}

//void QVTKInteractorStyle::test() {
//	vtkCamera* camera = _renderer->GetActiveCamera();
//	double *eyePos = camera->GetPosition();
//	// 获取目标点坐标
//	double* focalPoint = camera->GetFocalPoint();
//	gp_Pnt EyePoint(eyePos[0], eyePos[1], eyePos[2]);
//	gp_Pnt AtPoint(focalPoint[0], focalPoint[1], focalPoint[2]);
//	gp_Vec EyeVector(EyePoint, AtPoint);
//	gp_Dir EyeDir(EyeVector);
//
//	gp_Pnt aPnt;
//	gp_Dir aDir;
//
//	pickNearestPoint(pickPos, EyeDir, Sh, aPnt, aDir, TopAbs_EDGE);
//}

/*计算两个Shape间的外部距离
计算两个形状之间的最小外部距离，即从一个形状的表面到另一个形状的表面的最短距离。
如果两个形状不相交，这个距离将是正的；如果它们相交，距离将是零。*/
Standard_Real QVTKInteractorStyle::DistanceOut(const TopoDS_Shape& S1, const TopoDS_Shape& S2)
{
	//提供了一个边界框来存储更复杂数据结构,通常用于空间检索和几何测试
	Bnd_Box BBox1, BBox2;
	BRepBndLib::Add(S1, BBox1);
	BRepBndLib::Add(S2, BBox2);
	return BBox1.Distance(BBox2);
}

//计算边中点拾取
TopoDS_Shape QVTKInteractorStyle::pickNearestEdgePoint(const gp_Pnt& P, const TopoDS_Shape& S)
{
	TopoDS_Vertex nearstVertex;
	//映射容器，用于存储 TopoDS_Shape 对象的索引映射
	TopTools_IndexedMapOfShape M;
	//遍历 S 中的所有点	将点的索引添加到 M 中
	TopExp::MapShapes(S, TopAbs_VERTEX, M);
	int count = M.Extent();
	if (count == 0) return TopoDS_Vertex();
	gp_Pnt tempProjPnt;
	gp_Pnt middlePnt(0,0,0);
	//定义最近点的最大距离
	double maxDis = 0.2, dis;
	
	for (int i = 1; i <= count; i++)
	{
		const TopoDS_Vertex& vertex = TopoDS::Vertex(M.FindKey(i));
		
		tempProjPnt = BRep_Tool::Pnt(vertex);
		middlePnt.SetX(middlePnt.X() + tempProjPnt.X());
		middlePnt.SetY(middlePnt.Y() + tempProjPnt.Y());
		middlePnt.SetZ(middlePnt.Z() + tempProjPnt.Z());
		dis = tempProjPnt.Distance(P);
		if (dis < maxDis)
		{
			maxDis = dis;
			nearstVertex = vertex;
		}
	}
	if (count == 2) {
		middlePnt.SetX(middlePnt.X() / 2);
		middlePnt.SetY(middlePnt.Y() / 2);
		middlePnt.SetZ(middlePnt.Z() / 2);
		dis = middlePnt.Distance(P);
		if (dis < maxDis) {
			maxDis = dis;
			BRepBuilderAPI_MakeVertex makeVertex(middlePnt);
			const TopoDS_Vertex& vertex = makeVertex.Vertex();
			nearstVertex = vertex;
		}
	}
	return nearstVertex;
}

/*计算两个Shape间的内部距离
计算两个形状之间的最大内部距离，
即从一个形状内部的任意点到另一个形状内部的任意点的最大距离。*/
Standard_Real QVTKInteractorStyle::DistanceIn(const TopoDS_Shape& S1, const TopoDS_Shape& S2)
{
	Bnd_Box LBBox, SBBox;
	BRepBndLib::Add(S1, SBBox);
	BRepBndLib::Add(S2, LBBox);

	Standard_Real LXmin, LYmin, LZmin, LXmax, LYmax, LZmax,
		SXmin, SYmin, SZmin, SXmax, SYmax, SZmax;
	SBBox.Get(SXmin, SYmin, SZmin,
		SXmax, SYmax, SZmax);
	LBBox.Get(LXmin, LYmin, LZmin,
		LXmax, LYmax, LZmax);

	//Compute the max distance between input shapes------------//
	gp_XYZ Lmin(LXmin, LYmin, LZmin),
		Lmax(LXmax, LYmax, LZmax);
	gp_XYZ Smin(SXmin, SYmin, SZmin),
		Smax(SXmax, SYmax, SZmax);
	Lmax.Subtract(Lmin);
	Smax.Subtract(Smin);
	//两个边界框的对角线长度和它们的外部距离相加，得到两个形状之间的最大内部距离
	return Lmax.Modulus() + Smax.Modulus() + DistanceOut(S1, S2);
}

/*参数含义:
P：用户点击的屏幕坐标点，转换到世界坐标系中。
viewDir：视图方向，用于确定视线方向。
S：要搜索最近点的形状。
relPoint：找到的最近点。
faceNormal：如果需要，找到的最近点所在面的法线。
onlyEdges：布尔值，指示是否只在边（edges）上寻找最近点。
*/

//顶层Actor获取边 即S为Edge 类型
//获取S中所有的点，遍历得到最近点。
//bool QVTKInteractorStyle::pickNearestPoint(const gp_Pnt& P, const gp_Dir& viewDir, const TopoDS_Shape& S, gp_Pnt& relPoint, gp_Dir& faceNormal, bool onlyEdges)
//{
//	if (S.IsNull())
//		return false;
//
//	if (onlyEdges)
//	{
//		//映射容器，用于存储 TopoDS_Shape 对象的索引映射
//		TopTools_IndexedMapOfShape M;
//		//遍历 S 中的所有边	将边的索引添加到 M 中
//		TopExp::MapShapes(S, TopAbs_EDGE, M);
//		int count = M.Extent();
//		if (count == 0) return false;
//		gp_Pnt tempProjPnt;
//		gp_Dir tempProjPntFaceNormal;
//		double maxDis = Precision::Infinite(), dis;
//		bool isOk = false;
//		for (int i = 1; i <= count; i++)
//		{
//			const TopoDS_Edge& E = TopoDS::Edge(M.FindKey(i));
//			TopoDS_Vertex aFirstVertex = TopExp::FirstVertex(E);
//
//			tempProjPnt = BRep_Tool::Pnt(aFirstVertex);
//
//			if (pickNearestPoint(P, viewDir, E, tempProjPnt, tempProjPntFaceNormal, false))
//			{
//				dis = tempProjPnt.Distance(P);
//				if (dis < maxDis)
//				{
//					maxDis = dis;
//					relPoint = tempProjPnt;
//				}
//				isOk = true;
//			}
//		}
//		return isOk;
//	}
//	else
//	{
//		double d = DistanceIn(BRepBuilderAPI_MakeVertex(P), S);
//		gp_Vec Vsup(viewDir.XYZ() * 2 * d);
//
//
//		TopoDS_Edge tempEdge = BRepBuilderAPI_MakeEdge(P.Translated(-1 * Vsup), P.Translated(Vsup)/*EyePoint*/);
//		bool ok = false;
//		//速度快
//		if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE)
//		{
//			if (S.ShapeType() == TopAbs_EDGE)
//			{
//				BRepExtrema_ExtCC ext(tempEdge, TopoDS::Edge(S));
//				if (ext.IsDone() && ext.NbExt() > 0)
//				{
//					//get min distance
//					double distance = Precision::Infinite();
//					for (int i = 1; i <= ext.NbExt(); i++)
//					{
//						Standard_Real d = ext.SquareDistance(i);
//						if (d < distance)
//						{
//							relPoint = ext.PointOnE2(i);
//							distance = d;
//							ok = true;
//						}
//					}
//				}
//			}
//		}
//	}
//	return true;
//}

//TopoDS_Vertex QVTKInteractorStyle::pickNearestEdgePoint(const gp_Pnt& P, const TopoDS_Shape& S)
//{
//	TopoDS_Vertex nearstVertex;
//	//映射容器，用于存储 TopoDS_Shape 对象的索引映射
//	TopTools_IndexedMapOfShape M;
//	//遍历 S 中的所有边	将边的索引添加到 M 中
//	TopExp::MapShapes(S, TopAbs_VERTEX, M);
//	int count = M.Extent();
//	if (count == 0) return TopoDS_Vertex();
//	gp_Pnt tempProjPnt;
//
//	double maxDis = Precision::Infinite(), dis;
//
//	for (int i = 1; i <= count; i++)
//	{
//		const TopoDS_Vertex& vertex = TopoDS::Vertex(M.FindKey(i));
//
//		tempProjPnt = BRep_Tool::Pnt(vertex);
//
//		dis = tempProjPnt.Distance(P);
//		if (dis < maxDis)
//		{
//			maxDis = dis;
//			nearstVertex = vertex;
//		}
//
//	}
//	return nearstVertex;
//}
